
import Vuex from "vuex";
import Vue from "vue";

Vue.use(Vuex);

// 无需手动引入模块，自动引入modules下的所有模块
const modulesFiles = require.context('./modules', true, /\.js$/)
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
  // 通过文件名导入模块，比如：'./app.js' => 'app'
  const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
  const value = modulesFiles(modulePath)
  modules[moduleName] = value.default
  return modules
}, {})

// 将所有模块的state映射到getters中，使用 “模块名/数据名” 的方式调用
const getters = {};
Object.keys(modules).forEach((item) => {
  const module = modules[item];
  if (module.getters) {
    Object.keys(module.state).forEach((key) => {
      getters[`${item}/${key}`] = (state) => {
        const CurrentStateValue = state[item][key];
        const StorageValue = localStorage.getItem(`${item}.${key}`);
        if (StorageValue && StorageValue !== JSON.stringify(CurrentStateValue)) {
          state[item][key] = JSON.parse(StorageValue);
        }
        return state[item][key];
      }
    });
  }
});

const store = new Vuex.Store({
  modules,
  getters,
});

/**
 * 功能：持久化存储
 * 监听每个模块的mutation，如果mutation的type中包含了 '_PERSIST' 后缀标识，则将该模块的state存储到localStorage中;
 * 规则：
 * store中的state的key必须使用小驼峰命名法，mutation中的Key使用 “操作符_下划线分隔大写[_PERSIST]” 格式命名，
 * 如：mutation中的 'SET_USER_INFO_PERSIST' 和 'DELETE_USER_INFO_PERSIST' ，对应的state的key为 'userInfo'
 * 注意：
 * 每个state的Key对应的操作符必须后缀（_PERSIST）统一,都带或者都不带，如：'SET_USER_INFO_PERSIST' 和 'DELETE_USER_INFO_PERSIST'
 * 否则‘mapGetter’会出现问题
 */
store.subscribe((mutation, state) => {
  const StorageKey = mutation.type.split('/');
  const PayloadKey = StorageKey.pop().split('_');
  if (PayloadKey[PayloadKey.length - 1] === 'PERSIST') {
    // 删除最开始的操作标识
    PayloadKey.shift();
    // 删除最后的PERSIST标识
    PayloadKey.pop();
    let StateKey = '';
    // 将mutation的type转换为state的key
    PayloadKey.forEach((item, index) => {
      if (index === 0) {
        StateKey += item.toLowerCase();
      } else {
        StateKey += item.charAt(0).toUpperCase() + item.slice(1).toLowerCase();
      }
    });
    // 获取state的值
    let tempValue = state;
    for (const item of StorageKey) {
      tempValue = tempValue[item];
    }
    localStorage.setItem(`${StorageKey.join('.')}.${StateKey}`, JSON.stringify(tempValue[StateKey]));
    if (!tempValue[StateKey]) localStorage.removeItem(`${StorageKey.join('.')}.${StateKey}`);
  }
});

export default store;
